package com.bcx.wind.workflow.imp.cmd.corecmd;

import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.TaskLevel;
import com.bcx.wind.workflow.core.constant.TaskStatus;
import com.bcx.wind.workflow.core.constant.WorkflowOperate;
import com.bcx.wind.workflow.core.flow.NodeModel;
import com.bcx.wind.workflow.entity.WindOrder;
import com.bcx.wind.workflow.entity.WindProcess;
import com.bcx.wind.workflow.entity.WindProcessConfig;
import com.bcx.wind.workflow.entity.WindTask;
import com.bcx.wind.workflow.interceptor.Context;
import com.bcx.wind.workflow.pojo.Task;
import com.bcx.wind.workflow.pojo.Wind;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.pojo.variable.SubmitVariable;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.ObjectHelper;

import java.util.List;

import static com.bcx.wind.workflow.access.AccessSqlConstant.DESC;
import static com.bcx.wind.workflow.core.constant.Constant.WIND_ADMIN;
import static com.bcx.wind.workflow.message.ErrorCode.*;

/**
 * 提交工作流命令
 *
 * @author zhanglei
 */
public class SubmitCommand extends BaseCommand {

    /**
     * 提交参数
     */
    private SubmitVariable variable;


    public SubmitCommand(SubmitVariable submitVariable){
        this.variable = submitVariable;
    }


    @Override
    public Wind execute() {
        this.wind().setOperate(WorkflowOperate.submit);
        //校验提交参数
        checkSubmitVariable();
        //提交
        submit();
        return this.wind();
    }

    /**
     * 校验参数  和 添加默认数据
     */
    private void checkSubmitVariable() {
        Assert.notEmptyError(SUBMIT_NOT_FOUND_ARGS,this.variable);
        Assert.notEmptyError(SUBMIT_FAIL,this.variable.getOrderId(),"orderId");
        initWind();
    }


    private void submit() {
        //构建流程实例流程定义
        buildOrderAndProcess();
        //构建流程配置
        buildProcessConfig();
        //构建当前任务  执行
        buildCurNode();
        //更新流程实例
        updateOrder();
    }


    /**
     * 最后更新流程实例
     */
    private void updateOrder(){
        commandContext.runtimeService().updateOrder(wind().getWindOrder());
    }



    /**
     * 构建当前任务以及当前任务配置
     */
    private  void  buildCurNode(){
        WindOrder order = wind().getWindOrder();
        QueryFilter filter = new QueryFilter()
                .setOrderId(order.getId())
                .setStatus(TaskStatus.run.name())
                .setTaskLevel(TaskLevel.main.name());
        //如果当前流程操作不止一次，即当前流程不是初始化流程
        if(order.getVersion() > 1){
            filter.setTaskActorId(new String[]{user().getUserId()});
            if(variable.getTaskId() != null){
                filter.setTaskId(variable.getTaskId());
            }
        }
        //时间排序
        filter.setOrderBy(DESC);
        List<WindTask> tasks = commandContext.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(NOT_FOUND_TASK,tasks);
        //获取第一个任务进行提交
        WindTask windTask = tasks.get(0);
        Task task = buildCurNodeConfig(windTask.getTaskName(),windTask);
        this.wind().getCurNode().add(task);
        //保存当前操作时，流程数据，供后面撤销使用
        addRevokeData(windTask);
        //执行
        NodeModel taskModel = task.getTaskNode();
        taskModel.context(this.commandContext,task);
        taskModel.execute();
        //删除本地数据
        Context.remove();
    }


    /**
     * 初始化wind
     */
    private void  initWind(){
        this.wind().setOperator(user().getUserId())
                .setSystem(this.variable.getSystem())
                .setUser(this.user())
                .setSuggest(this.variable.getSuggest())
                .setSubmitNode(this.variable.getSubmitNode());
        if(variable.getArgs() != null){
            this.wind().setArgs(this.variable.getArgs());
        }
        if(variable.getVars() != null){
            this.wind().setVars(this.variable.getVars());
        }
        if(this.variable.getApproveUsers() != null){
            this.wind().setApproveUsers(this.variable.getApproveUsers());
        }
        if(this.variable.getSubmitPath() != null){
            this.wind().setSubmitPath(this.variable.getSubmitPath());
        }
    }


    /**
     * 当前流程配置
     */
    private void  buildProcessConfig(){
        String processName = wind().getWindProcess().getProcessName();
        WindProcessConfig processConfig = ObjectHelper.getNodeConfig(this.configList,processName,this.variable.getArgs());
        Assert.notEmptyError(PROCESS_CONFIG_NOT_FOUND,processConfig,processName,processName);
        this.wind().setWindConfig(buildWindConfig(processConfig));
    }


    /**
     * 设置当前流程实例  以及  实例使用的流程定义
     */
    private  void  buildOrderAndProcess(){
        String orderId = this.variable.getOrderId();
        WindOrder order = buildWindOrder(orderId);
        //所有任务
        wind().setAllTasks(tasks(orderId));
        //设置
        wind().setWindOrder(order);
        wind().setBusinessId(order.getBusinessId());
        //设置process
        String processId = order.getProcessId();
        WindProcess process = commandContext.repositoryService().queryById(processId);
        Assert.notEmptyError(PROCESS_QUERY_NULL,process,processId);

        wind().setWindProcess(process);
        //设置当前流程所有配置
        getConfigList(processId);
    }



    /**
     * 当前用户  默认使用 wind_admin
     * @return  当前用户
     */
    private WindUser  user(){
        WindUser user = this.variable.getUser();
        if(user == null){
            user = new WindUser()
                    .setUserId(WIND_ADMIN)
                    .setUserName("管理员");
        }
        return user;
    }


}
